<template>
    <div>
        <div class="button">
            <el-button type="primary" :icon="Plus" @click="add">添加</el-button>
        </div>
        <div class="table">
            <tableLayout
                :tableData="state.tableData"
                :data="state.data"
                :loading="state.loading"
                @operationChange="operationChange"
            ></tableLayout>
        </div>
        <el-dialog
            v-model="state.dialogFormVisible"
            width="30%"
            @close="cancel"
            @open="opendialog(form)"
            @closed="closedorgan"
            :title="state.title"
            :close-on-click-modal="false"
        >
            <el-form :model="state.form" ref="form" :rules="state.rules">
                <el-form-item label="角色名称" prop="name">
                    <el-input v-model="state.form.name" placeholder="输入角色名称" />
                </el-form-item>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="cancel(form)">取消</el-button>
                    <el-button type="primary" @click="submit(form)">保存</el-button>
                </span>
            </template>
        </el-dialog>
        <el-dialog
            v-model="state.permission"
            width="30%"
            @close="permissionCancel"
            @closed="permissionClosedorgan"
            :title="state.permissionTitle"
            :close-on-click-modal="false"
        >
            <el-input
                v-model="state.filterText"
                clearable
                @keyup.enter="getfilter"
                @clear="getfilter"
                placeholder="请输入"
            />
            <el-tree
                ref="treeRef"
                class="filter-tree"
                node-key="id"
                show-checkbox
                :data="state.treeData"
                :props="state.defaultProps"
                @check="handleCheckChange"
                :filter-node-method="filterNode"
                :default-checked-keys="defaultCheckedKeys"
            />
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="permissionCancel">取消</el-button>
                    <el-button type="primary" @click="permissionSubmit">保存</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { reactive, onMounted, ref, nextTick, watch } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import API from '@/api';
import { ElMessage, ElMessageBox, ElTree } from 'element-plus';
import type { FormInstance } from 'element-plus';
import tableLayout from '@/dynamicCustom/components/tableLayout.vue';
const form = ref<FormInstance>();

interface Tree {
    id: number;
    name: string;
    children?: Tree[];
}

const treeRef = ref<InstanceType<typeof ElTree>>();
const state = reactive({
    tableData: [],
    loading: false,
    filterText: '',
    treeData: [],
    defaultProps: {
        children: 'children',
        label: 'name'
    },
    data: [
        { label: '角色名称', prop: 'name' },
        { label: '创建时间', prop: 'createTime' },
        {
            label: '操作',
            slotName: 'operation',
            operation: [
                {
                    label: '权限配置',
                    types: 'primary',
                    onClick: 'rightsProfile'
                },
                {
                    label: '修改',
                    types: 'primary',
                    onClick: 'reviseRole'
                },
                {
                    label: '删除',
                    types: 'primary',
                    onClick: 'deleteRole'
                }
            ]
        }
    ] as any[],
    title: '添加角色',
    permissionTitle: '角色授权菜单',
    dialogFormVisible: false,
    permission: false,
    rules: {
        name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }]
    },
    form: {
        name: ''
    } as any,
    list: [],
    checkedKeys: [],
    roleId: ''
});
const defaultCheckedKeys = ref([]);

//权限配置
const rightsProfile = async (id: string) => {
    state.list = [];
    defaultCheckedKeys.value = []; // 清空
    state.permission = true;
    await getAuthTree(id);
};

//权限配置初始化接口
const getAuthTree = async (id: string) => {
    state.roleId = id;
    try {
        const resp = await API.role_authTree({ data: { roleId: id }, method: 'GET' });
        state.treeData = resp;
        const map = listobj(resp);
        const check = map.filter(res => res.isChecked && res.isButton);
        check.forEach(res => {
            defaultCheckedKeys.value.push(res.id);
        });
    } catch (err) {}
};
const listobj = (arr: any) => {
    arr.forEach((row: any) => {
        state.list.push(row);
        if (row.children) {
            listobj(row.children); // 递归
        }
    });
    return state.list;
};
//递归操作数组拉平
const getObj = (arr: any) => {
    const arr1 = new Set(state.checkedKeys);
    const arr2 = new Set(defaultCheckedKeys.value);
    const deleteArr: any[] = [];
    const addArr: any[] = [];
    const someArr = [...new Set([...arr1].filter(x => arr2.has(x)))];
    arr2.forEach(item => {
        if (someArr.indexOf(item) === -1) {
            deleteArr.push(item);
        }
    });
    arr1.forEach(item => {
        if (someArr.indexOf(item) === -1) {
            addArr.push(item);
        }
    });
    arr.forEach((row: any) => {
        row.roleId = state.roleId;
        row.menuId = row.id.split(':')[0];
        if (row.isLast != undefined) {
            state.list.push(row);
        }
        var arr = [];
        if (row.children) {
            for (let i = 0; i < row.children.length; i++) {
                deleteArr.forEach((res1: string) => {
                    if (row.children[i].id === res1) {
                        row.children[i].isChecked = false;
                    }
                });
                addArr.forEach((res2: string) => {
                    if (row.children[i].id === res2) {
                        row.children[i].isChecked = true;
                    }
                });
                row.children[i]['parentName'] = row.name;
                if (row.children[i]['isChecked']) {
                    arr.push(row.children[i]['name']);
                }
                row.children[i].roleId = state.roleId;
                row.children[i].menuId = row.children[i].id.split(':')[0];
                row.children[i].id = row.children[i].id.split(':')[0];
            }
            getObj(row.children);
        }
        if (row['isLast']) {
            if (arr.length) {
                row['menuButton'] = arr.join(',');
            }
        }
    });
    return state.list;
};

//搜索框点击回车或点击空处的时候
const getfilter = () => {
    treeRef.value!.filter(state.filterText);
};

const filterNode = (value: string, data: Tree) => {
    if (!value) return true;
    return data.name.includes(value);
};

//	点击节点复选框之后触发
const handleCheckChange = (val: object, option: object) => {
    state.checkedKeys = option.checkedKeys;
};

const getdata = () => {
    state.list = [];
    const treeData = state.treeData;
    const map = getObj(treeData);
    const list = JSON.parse(JSON.stringify(map));
    return list;
};
//关闭权限弹框后
const permissionCancel = () => {
    state.permission = false;
};
//关闭权限树形回调
const permissionClosedorgan = () => {
    state.roleId = '';
    state.checkedKeys = [];
    defaultCheckedKeys.value = [];
    state.treeData = [];
    state.list = [];
    state.filterText = '';
};
const permissionSubmit = async () => {
    const data: any[] = getdata();
    try {
        const resp = await API.role_addRoleMenu({
            data: JSON.stringify(data),
            method: 'POST',
            isJsonType: true
        });
        ElMessage.success('保存成功');
        state.permission = false;
    } catch (err) {}
};

const cancel = (form: FormInstance | undefined) => {
    state.dialogFormVisible = false;
};

const opendialog = (form: FormInstance | undefined) => {
    if (!form) return;
    nextTick(() => {
        form.clearValidate();
    });
};
//关闭弹框的回调
const closedorgan = () => {
    state.form = {
        name: ''
    };
};
//添加表单
const add = () => {
    state.title = '添加角色';
    state.dialogFormVisible = true;
};

const reviseRole = ({ id, name }) => {
    state.title = '修改角色';
    state.dialogFormVisible = true;
    state.form = {
        id,
        name
    };
};

const deleteRole = (id: string) => {
    ElMessageBox.confirm('确认删除', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    })
        .then(async () => {
            try {
                let res = await API.admin_role({ urlVal: id, method: 'DELETE' });
                ElMessage.success('删除成功');
                state.loading = true;
                getRole();
            } catch (err) {}
        })
        .catch(() => {
            ElMessage({
                type: 'info',
                message: '已取消删除'
            });
        });
};

// 表格按钮回调
const operationChange = (data: any) => {
    const a: any = {
        rightsProfile: () => rightsProfile(data.row.id),
        reviseRole: () => reviseRole(data.row),
        deleteRole: () => deleteRole(data.row.id)
    };
    a[data.eventName]();
};

const getreset = () => {
    state.dialogFormVisible = false;
    state.loading = true;
    getRole();
};

// 点击保存
const submit = (form: FormInstance | undefined) => {
    if (!form) return;
    form.validate(async valid => {
        if (valid) {
            let apiName = state.form.id ? API.role_update : API.role_add;
            let Method = state.form.id ? 'PUT' : 'POST';
            const data = state.form.id ? { id: state.form.id, name: state.form.name } : { name: state.form.name };
            try {
                const resp = await apiName({ data: data, method: Method });
                ElMessage.success('操作成功');
                getreset();
            } catch (error) {
                state.dialogFormVisible = false;
            }
        }
    });
};

const getRole = async () => {
    try {
        state.loading = false;
        const resp = await API.role_list({ method: 'GET' });
        state.tableData = resp;
    } catch (err) {
        state.loading = false;
    }
};

onMounted(() => {
    state.loading = true;
    getRole();
});
</script>
<style lang="scss" scoped>
.button {
    margin: 15px;
}

.table {
    height: 80%;
}

.dialog-footer {
    button:first-child {
        margin-right: 10px;
    }
}
</style>
